/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.flexengine.sound;

import com.flexengine.logger.Logger;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 * @author Luann R. Athayde
 * @version 1.0
 * @since 1.0
 */
public class Sound {
    
    /**
     * Sound type unknown...
     */
    public static final int  SOUND_TYPE_UNK = 0x0000;
    /**
     * Sound type OGG...
     */
    public static final int  SOUND_TYPE_OGG = 0x000f;
    /**
     * Sound type WAV or WAVE...
     */
    public static final int  SOUND_TYPE_WAV = 0x00ff;
    /**
     * Sound type MIDI...
     */
    public static final int  SOUND_TYPE_MID = 0x0fff;
    /**
     * Sound type MP3...
     */
    public static final int  SOUND_TYPE_MP3 = 0xffff;
    
    private File             soundFile;
    private String           soundPath;
    private AudioInputStream audioStream;
    private AudioFormat      soundFormat;
    
    private byte[]           samples;
    
    private int              soundType;
    
    public Sound(String soundPath) {
        try {
            if( soundPath.endsWith(".ogg") ) {
                soundType = SOUND_TYPE_OGG;
            } else if( soundPath.endsWith(".wav") ) {
                soundType = SOUND_TYPE_WAV;
            } else if( soundPath.endsWith(".midi") || soundPath.endsWith(".mid") ) {
                soundType = SOUND_TYPE_MID;
            } else if( soundPath.endsWith(".mp3") ) {
                soundType = SOUND_TYPE_MP3;
            } else {
                soundType = SOUND_TYPE_UNK;
            }
            // -- ./resources/
            this.soundPath = soundPath.substring(12, soundPath.length());
            this.soundFile = new File(soundPath);
            if( soundType != SOUND_TYPE_MP3 && soundType != SOUND_TYPE_OGG ) {
                // -- get sound stream...
                audioStream = AudioSystem.getAudioInputStream(this.soundFile);
                // -- get sound format...
                soundFormat = audioStream.getFormat();
                // -- get sound samples...
                samples = Sound.getSamples(audioStream, soundFormat);
            } else {
                audioStream = null;
                soundFormat = null;
                samples     = null;
            }
        } catch(UnsupportedAudioFileException ue) {
            Logger.logError(getClass().getSimpleName()+" - Unsupported audio file ["+this.soundFile+"]...\n"
                    + "\tException: "+ue);
        } catch(IOException ioe) {
            Logger.logError(getClass().getSimpleName()+" - IO Exception in Sound constructor...\n"
                    + "\tException: "+ioe);
        } catch(NullPointerException npe) {
            Logger.logError(getClass().getSimpleName()+" - NullPointer exception...\n"
                    + "\tException: "+npe);
        }
    }

    protected File getSoundFile() {
        return soundFile;
    }

    public AudioInputStream getAudioStream() {
        return audioStream;
    }

    public AudioFormat getSoundFormat() {
        return soundFormat;
    }

    public byte[] getSamples() {
        return samples;
    }

    public int getSoundType() {
        return soundType;
    }
    
    public static String getTypeName(int soundType) {
        switch(soundType) {
            case SOUND_TYPE_MID:
                return "Midi";
            case SOUND_TYPE_MP3:
                return "mp3";
            case SOUND_TYPE_OGG:
                return "ogg";
            case SOUND_TYPE_WAV:
                return "wav";
            case SOUND_TYPE_UNK:
            default:
                return "Unknown";
        }
    }
    
    public static byte[] getSamples(AudioInputStream inStream, AudioFormat format) {
        try {
            int len = (int)(inStream.getFrameLength()*format.getFrameSize());
            byte[] nSamples = new byte[len];
            DataInputStream dataStream = new DataInputStream(inStream);
            dataStream.readFully(nSamples);
            return nSamples;
        } catch(Exception e) {
            Logger.logError(Sound.class.getSimpleName()+" - getSamples(): "+e);
        }
        return null;
    }

    public String getSoundPath() {
        return soundPath;
    }
    
    @Override
    public String toString() {
        return "Sound{" + "fSound=" + soundFile + ", audioStream=" + audioStream + ", soundFormat=" + soundFormat +", soundType="+getTypeName(soundType)+'}';
    }
    
}
